package cn.fansunion.concurrent.threadabc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

//有3个线程ABC。按照ABC来运行（A线程输出A，B线程输出B，C线程输出C，以此类推，循环输出）。
//参考JDK官方文档，ReentrantLock和Condition
public class ThreadABCByLockCondition {

	public static void main(String[] args) {
		//循环次数
		final int maxNum = 5;
		ReentrantLock reentrantLock = new ReentrantLock();
		Condition aCondition = reentrantLock.newCondition();
		Condition bCondition = reentrantLock.newCondition();
		Condition cCondition = reentrantLock.newCondition();
		// 这个地方不能用String currentThread="A";线程内部，要加final，加了final就不能修改引用了
		final String[] currentThread = { "A" };
		Thread aThread = new Thread(new Runnable() {

			@Override
			public void run() {
				for (int index = 0; index < maxNum; index++) {
					reentrantLock.lock();
					try {
						//这个地方可以不用while
						if (currentThread[0] != "A") {
							aCondition.await();
						}
						System.out.print("A");
						currentThread[0] = "B";
						bCondition.signal();
					} catch (InterruptedException e) {
						e.printStackTrace();
					} finally {
						reentrantLock.unlock();
					}
				}
			}

		});

		Thread bThread = new Thread(new Runnable() {

			@Override
			public void run() {
				for (int index = 0; index < maxNum; index++) {
					reentrantLock.lock();
					try {
						if (currentThread[0] != "B") {
							bCondition.await();
						}
						System.out.print("B");
						currentThread[0] = "C";
						cCondition.signal();
					} catch (InterruptedException e) {
						e.printStackTrace();
					} finally {
						reentrantLock.unlock();
					}

				}

			}

		});

		Thread cThread = new Thread(new Runnable() {

			@Override
			public void run() {
				for (int index = 0; index < maxNum; index++) {
					reentrantLock.lock();
					try {
						if (currentThread[0] != "C") {
							cCondition.await();
						}
						System.out.print("C");
						// 打印1个换行
						System.out.println();
						currentThread[0] = "A";
						aCondition.signal();
					} catch (InterruptedException e) {
						e.printStackTrace();
					} finally {
						reentrantLock.unlock();
					}
				}

			}

		});
		aThread.start();
		bThread.start();
		cThread.start();

	}

}
